﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace AChance.Func
{
    public static class FunTask
    {
        /// <summary>
        /// 线程名称
        /// </summary>
        public static class Name
        {
            /// <summary>
            /// 系统
            /// </summary>
            public const string SYSTEM = "System";
            /// <summary>
            /// 业务
            /// </summary>
            public const string BUSINESS = "Business";
        }

        private static ConcurrentDictionary<string, TaskOper> _tasks = new ConcurrentDictionary<string, TaskOper>();

        /// <summary>
        /// 获取指定的线程操作类，如果不存在则自动创建
        /// </summary>
        public static TaskOper Get(string taskName, string serialNo = "")
        {
            var name = taskName + serialNo;
            return _tasks.GetOrAdd(name, new TaskOper(name));
        }
        /// <summary>
        /// 停止所有线程
        /// </summary>
        public static bool Stop()
        {
            bool result = true;
            foreach (TaskOper taskOper in _tasks.Values)
                result = result && taskOper.Stop();
            return result;
        }
        /// <summary>
        /// 线程操作
        /// </summary>
        public class TaskOper
        {
            /// <summary>
            /// 线程
            /// </summary>
            private Task Task { get; set; } = null;
            /// <summary>
            /// 线程名称
            /// </summary>
            private string Name { get; set; } = "";
            /// <summary>
            /// 判断线程是否想要停止
            /// </summary>
            public bool IsWantStop { get; private set; } = false;
            /// <summary>
            /// 线程启动时间
            /// </summary>
            public DateTime? StartTime { get; private set; } = null;
            /// <summary>
            /// 传出信息
            /// </summary>
            public string OutMsg { get; set; } = "";
            /// <summary>
            /// 传出信息详情
            /// </summary>
            public List<string> OutMsgDetail { get; set; } = new List<string>();

            public TaskOper(string name)
            {
                Name = name;
            }
            /// <summary>
            /// 启动线程
            /// </summary>
            public bool Start<T>(Action<T> runnable, T args)
            {
                return Start(() => runnable(args));
            }
            public bool Start(Action runnable)
            {
                if (!IsCompleted())
                    return true;
                IsWantStop = false;
                StartTime = DateTime.Now;
                OutMsg = "";
                OutMsgDetail = new List<string>();
                try
                {
                    Task = Task.Factory.StartNew(runnable, TaskCreationOptions.LongRunning);
                    return true;
                }
                catch (Exception ex)
                {
                    FunLogs.LogError("启动线程失败(" + Name + ")", ex);
                    return false;
                }
            }
            /// <summary>
            /// 停止线程
            /// </summary>
            public bool Stop()
            {
                if (IsCompleted())
                    return true;
                IsWantStop = true;
                try
                {
                    Task.Wait();
                    Task = null;
                    return true;
                }
                catch (Exception ex)
                {
                    FunLogs.LogError("停止线程失败(" + Name + ")", ex);
                    return false;
                }
            }
            /// <summary>
            /// 判断线程是否完成
            /// </summary>
            public bool IsCompleted()
            {
                return Task?.IsCompleted ?? true;
            }
        }

        public static class Context
        {
            private static ThreadLocal<ConcurrentDictionary<string, object>> _context = new ThreadLocal<ConcurrentDictionary<string, object>>();
            private static ConcurrentDictionary<string, object> Value
            {
                get
                {
                    return _context.Value ??= new ConcurrentDictionary<string, object>();
                }
            }
            public static ConcurrentDictionary<string, object> TransOper
            {
                get
                {
                    return (ConcurrentDictionary<string, object>)Value.GetOrAdd(nameof(TransOper), new ConcurrentDictionary<string, object>());
                }
            }
            public static ConcurrentDictionary<string, object> SqlOper
            {
                get
                {
                    return (ConcurrentDictionary<string, object>)Value.GetOrAdd(nameof(SqlOper), new ConcurrentDictionary<string, object>());
                }
            }
        }


    }
}
